# No copyright
import asyncio
import logging

class Player:
  def __init__(self, pb):
    self._pb    = pb
    self.assets = {}
    self.orders = {}

  async def cancel(self, pair, orders):
    res = await self._post("user/spot/cancel_orders", data={
      "pair": f"{pair[0]}_{pair[1]}",
      "order_ids": orders
    })

  async def orderMarketSell(self, pair, amount):
    res = await self._post("user/spot/order", data={
      "pair": f"{pair[0]}_{pair[1]}",
      "amount": str(amount),
      "side": "sell",
      "type": "market",
    })
    return res["data"]["order_id"]

  async def orderMarketBuy(self, pair, amount):
    res = await self._post("user/spot/order", data={
      "pair": f"{pair[0]}_{pair[1]}",
      "amount": str(amount),
      "side": "buy",
      "type": "market",
    })
    return res["data"]["order_id"]

  async def orderLimitSell(self, pair, amount, price):
    res = await self._post("user/spot/order", data={
      "pair": f"{pair[0]}_{pair[1]}",
      "amount": str(amount),
      "price": str(price),
      "side": "sell",
      "type": "limit",
    })
    return res["data"]["order_id"]

  async def orderLimitBuy(self, pair, amount, price):
    res = await self._post("user/spot/order", data={
      "pair": f"{pair[0]}_{pair[1]}",
      "amount": str(amount),
      "price": str(price),
      "side": "buy",
      "type": "limit",
    })
    return res["data"]["order_id"]

  async def update(self):
    self.assets = {}
    self.orders = {}

    assets = (await self._get("user/assets"))["data"]["assets"]
    for asset in assets:
      self.assets[asset["asset"]] = Asset(asset)

    orders = (await self._get("user/spot/active_orders"))["data"]["orders"]
    for order in orders:
      self.orders[order["order_id"]] = Order(order)

  async def _post(self, suffix, data):
    for i in range(10):
      try:
        res = await self._pb.post(f"https://api.bitbank.cc/v1/{suffix}", data=data)
        return self._check(await res.json())
      except Exception as e:
        err = e
        await asyncio.sleep(1)
    raise Exception(f"API error: {suffix} ({err})")

  async def _get(self, suffix):
    for i in range(10):
      try:
        res = await self._pb.get(f"https://api.bitbank.cc/v1/{suffix}")
        return self._check(await res.json())
      except Exception as e:
        err = e
        await asyncio.sleep(1)
    raise Exception(f"API error: {suffix} ({err})")

  def _check(self, json):
    if "success" not in json or 1 != json["success"]:
      code = json["data"]["code"]
      raise Exception(f"API error: {code}")
    return json


class Asset:
  def __init__(self, json):
    self.name      = json["asset"]
    self.amount    = float(json["onhand_amount"])
    self.locked    = float(json["locked_amount"])
    self.precision = int(json["amount_precision"])

class Order:
  def __init__(self, json):
    self.id     = json["order_id"]
    self.pair   = json["pair"]
    self.amount = float(json["start_amount"])
    self.remain = float(json["remaining_amount"])
    self.price  = float(json["average_price"])
